package org.halk.nio;

import org.junit.Test;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author halk
 * @date 2023/4/11
 */
public class BufferDemo {

    /**
     * buffer测试
     */
    @Test
    public void bufferTest() {
        IntBuffer intBuffer = IntBuffer.allocate(5);

        for (int i = 0; i < 5; i++) {
            intBuffer.put(i);
        }

        //翻转缓冲区，将指针放到头部
        intBuffer.flip();

        while (intBuffer.hasRemaining()) {
            int i = intBuffer.get();
            System.out.println(i);
        }

        System.out.println("position当前的位置： " + intBuffer.position());
        System.out.println("获得下标为2的数据：" + intBuffer.get(2));
        intBuffer.position(4);
        System.out.println(intBuffer.get());

        //调用flip后会将当前的下标position赋值给limit，
        intBuffer.position(2);
        intBuffer.flip();
        intBuffer.flip();

        while (intBuffer.hasRemaining()) {
            int i = intBuffer.get();
            System.out.println(i);
        }

        System.out.println(1);
    }

    /**
     * 放入什么类型的数据就要用什么类型读取出来
     * 使用索引获取，将会改变position的位置，全程都需要用索引获取
     */
    @Test
    public void bufferGetPut() {
        //可以放入100字节的数据
        ByteBuffer byteBuffer = ByteBuffer.allocate(100);

        //int占用4个字节
        byteBuffer.putInt(2);
        //double占用8个
        byteBuffer.putDouble(3L);
        byteBuffer.putChar('1');
        byteBuffer.putShort((short) 12);

        byteBuffer.flip();

        System.out.println(byteBuffer.getInt());
        System.out.println(byteBuffer.getDouble());
        System.out.println(byteBuffer.getChar());
        System.out.println(byteBuffer.getShort());

//        while (byteBuffer.hasRemaining()) {
//            int i = byteBuffer.get();
//            System.out.println(i);
//        }
    }

    /**
     * 只读buffer不能往里面放入数据
     */
    @Test
    public void readOnlyBuffer() {
        IntBuffer intBuffer = IntBuffer.allocate(100);
        for (int i = 0; i < 5; i++) {
            intBuffer.put(i);
        }

        intBuffer.flip();
        IntBuffer readOnlyBuffer = intBuffer.asReadOnlyBuffer();

        while (readOnlyBuffer.hasRemaining()) {
            System.out.println(readOnlyBuffer.get());
        }

        //只读，不可以放入数据
        readOnlyBuffer.put(11);
    }

    /**
     * MappedByteBuffer 可以让文件直接在内存（堆外内存）修改，操作系统不需要在拷贝一次、
     * 效率比较高
     *
     * @throws IOException
     */
    @Test
    public void mappedByteBufferTest() throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile("1.txt", "rw");

        FileChannel channel = randomAccessFile.getChannel();

        //可以从第0个索引起修改5个索引内的内容
        MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
        mappedByteBuffer.put(0, (byte) 'H');
        mappedByteBuffer.put(2, (byte) 'T');
        mappedByteBuffer.put(3, (byte) 'T');

        //超出了定义的大小
//        mappedByteBuffer.put(5, (byte) 'Q');

        randomAccessFile.close();
        System.out.println("修改完成");
    }
}
